package grib2handler.grib.ftp;

import java.io.PrintWriter;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool.Config;
import org.apache.log4j.Logger;

public class FTPPoolableObjectFactory extends BasePoolableObjectFactory{	
	private final static Logger logger = Logger.getLogger( FTPPoolableObjectFactory.class );

	private String host;
	private int port;
	private String user;
	private String password;
        private String passiveModeConf;
    
    public FTPPoolableObjectFactory(String host,int port,String user,String password,String passiveModeConf){
    	this.host = host;
    	System.out.println("host:"+host);
    	this.port = port;
    	System.out.println("port:"+port);
    	this.user = user;
    	System.out.println("user:"+user);
    	this.password = password;
    	System.out.println("password:"+password);
    	this.passiveModeConf = passiveModeConf;
    	System.out.println("passiveModeConf:"+passiveModeConf);
    }
    
	@Override
	public Object makeObject() throws Exception {
           FTPClient ftpClient = new FTPClient();
           ftpClient.setDefaultTimeout(60000);
           ftpClient.setConnectTimeout(60000);
		   ftpClient.setDataTimeout(60000); //数据传输2分钟超时
		  
		   //超时时间必须设置，防止长时间连接没响应
           ftpClient.setControlKeepAliveReplyTimeout(15000);
           //During file transfers, the data connection is busy, but the control connection is idle. FTP servers know that the control connection is in use, so won't close it through lack of activity, but it's a lot harder for network routers to know that the control and data connections are associated with each other. Some routers may treat the control connection as idle, and disconnect it if the transfer over the data connection takes longer than the allowable idle time for the router. 
           ftpClient.setControlKeepAliveTimeout(30); //sends a keepalive every thirty seconds
           
           ftpClient.connect(host, port);
           
           ftpClient.setSoTimeout(60000); //如果不设置，可能在执行completePendingComannd时阻塞，至此无限时阻塞在此
           ftpClient.login(user, password);
           boolean passiveMode = false;
           if (passiveModeConf == null || Boolean.parseBoolean(passiveModeConf) == true){
               passiveMode = true;
           }
           if (passiveMode) {
               ftpClient.enterLocalPassiveMode();
           } else {
        	   ftpClient.enterLocalActiveMode();
           }
           ftpClient.setBufferSize(10240);
           ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
           ftpClient.addProtocolCommandListener(new PrintCommandListener(
   				new PrintWriter(System.out)));
           ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter("log/ftplog.log")));
           logger.info("创建ftp新连接" + ftpClient.toString());
           return ftpClient;
	}

	@Override
	public void destroyObject(Object obj) throws Exception {
		if(obj instanceof FTPClient){
			FTPClient ftpClient=(FTPClient)obj;
			if(!ftpClient.isConnected()) return ;
			try{
				ftpClient.disconnect();
			}catch(Exception e){
				e.printStackTrace();
			}
			logger.info("销毁ftp连接" + ftpClient.toString());
		}
	}
	@Override
	public boolean validateObject(Object obj) {
		boolean flag = false;
		String msg = "Connection closed";
		FTPClient ftpClient = null;
		if(obj instanceof FTPClient){
			ftpClient = (FTPClient)obj;
			try{
				if(ftpClient.getReplyCode() == 421 || 
						ftpClient.getReplyCode() == 425 ) {
					//421超时      425Failed to establish connection
					flag = false;
					msg = ftpClient.getReplyString();
				} else {
					flag = ftpClient.isConnected();
				}
			}catch(Exception e){
				flag = false;
				msg = e.getMessage();
			}
		}
		if(!flag) {
			logger.warn("验证连接出现异常："  + ftpClient.toString() + msg);
		}
		return flag;
	}
	
	public static void main(String[] args) throws Exception{
		GenericObjectPool.Config config = new Config();
		//最大池容量
		config.maxActive=5;
		//从池中取对象达到最大时,继续创建新对象.
		config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
		//池为空时取对象等待的最大毫秒数.
		config.maxWait=60*1000;
		//取出对象时验证(此处设置成验证ftp是否处于连接状态).
		config.testOnBorrow=true;
		//还回对象时验证(此处设置成验证ftp是否处于连接状态).
		config.testOnReturn=true;
		FTPPool pool = new FTPPool(config,"ftp.ncep.noaa.gov",21,"anonymous","","true");
		System.out.println("borrowSize1:"+pool.borrowSize());
		System.out.println("inPoolSize1:"+pool.inPoolSize());
		long begin=System.currentTimeMillis();
		for(int i=0;i<100;i++){
			FTPClient ftpClient = pool.getResource();
			System.out.println("ftpClient"+(i+1)+" isConnected:"+ftpClient.isConnected());
			//ftpClient.disconnect();
			//pool.returnResource(ftpClient);
			pool.returnResource(ftpClient);
		}
		System.out.println("time:"+(System.currentTimeMillis()-begin));
		System.out.println("borrowSize2:"+pool.borrowSize());
		System.out.println("inPoolSize2:"+pool.inPoolSize());
		pool.destroy();
	}
}